﻿using System;
using BestHTTP.WebSocket;
using Cysharp.Threading.Tasks;
using LitJson;
using UnityEngine;

namespace HsVoice
{
    public class HsSynthWS
    {
        private byte[] reqHeader = { 0x11, 0x10, 0x11, 0x00 };
        private WebSocket ws;
        private SHsSynth sHsSynth;
        public HsSynthHandle handle;


        public HsSynthWS()
        {
            sHsSynth = new SHsSynth();
            handle = new HsSynthHandle();
        }
        public void LinkHsSynth()
        {
            if (ws != null && ws.IsOpen)
                ws.Close();
            Uri uri = new Uri(HsApp.WSS_SYNTHESIZER);
            ws = new WebSocket(uri);
            ws.InternalRequest.SetHeader("Authorization", "Bearer; " + HsApp.APP_TOKEN);
            ws.OnOpen += OnOpen;
            ws.OnBinary += OnBinaryReceived;
            ws.OnError += OnError;
            ws.OnClosed += OnClosed;
            ws.Open();
        }

        public void DislinkHsSynth()
        {
            if (ws != null && ws.IsOpen)
            {
                ws.Close();
            }
        }

        public async void SynthRequest(HsSynthRequest request)
        {
    
            await UniTask.WaitUntil(() => ws.IsOpen);
            byte[] body = JsonMapper.ToJson(request).ToBytes().ToGzip();
            byte[] bodyLen = body.Length.ToBytes().ToBitEndian();
            byte[] req = reqHeader.MergeBytes(bodyLen, body);
            ws.Send(req);
        }


        private void OnClosed(WebSocket websocket, ushort code, string message)
        {
            Debug.Log("[ 火山引擎智能语音合成websocket 关闭 ]");
        }

        private void OnError(WebSocket websocket, Exception ex)
        {
        }

        private void OnBinaryReceived(WebSocket websocket, byte[] buffer)
        {
            //int protocolVersion = (buffer[0] & 0xff) >> 4;  //暂时没使用，注释掉减少计算量
            //int headerSize = buffer[0] & 0x0f;              //暂时没使用，注释掉减少计算量
            int messageType = (buffer[1] & 0xff) >> 4;
            int messageTypeSpecificFlags = buffer[1] & 0x0f;
            //int serializationMethod = (buffer[2] & 0xff) >> 4; //暂时没使用，注释掉减少计算量
            //int messageCompression = buffer[2] & 0x0f;     //暂时没使用，注释掉减少计算量
            //int reserved = buffer[3] & 0xff;               //暂时没使用，注释掉减少计算量
            byte[] payload = buffer.SclieFormIndex(4);

            switch (messageType)
            {
                case HsApp.SYNTH_SUCCRSS:
                    if (messageTypeSpecificFlags == 0)
                    {
                        //服务器相应标志，不需要处理
                        Debug.Log($"[火山引擎语音合成 服务器相应]");
                    }
                    else
                    {
                        try
                        {
                            int sequenceNumber = payload.Sclie(0, 4).BytesToInt32();
                            //int payloadSize = payload.Sclie(4, 4).ToLittleEndian().BytesToInt32(); //暂时没使用，注释掉减少计算量
                            byte[] audioData = payload.SclieFormIndex(8);
                            sHsSynth.payload.Add(audioData);
                            handle.Write(audioData);
                            if (sequenceNumber < 0)
                            {
                                sHsSynth.isEnd = true;
                                handle.LoadAudio();
                                Debug.Log($"[火山引擎语音合成 完成~] ");
                            }
                        }
                        catch (Exception e)
                        {
                            Debug.Log(e.Message);
                            ws.Close();
                        }
                    }
                    break;
                case HsApp.SYNTH_ERROR:
                    int errorCode = payload.Sclie(0, 4).ToLittleEndian().BytesToInt32();
                    Debug.Log($"[火山引擎语音合成 错误码] : {errorCode}");
                    break;
                case HsApp.SYNTH_UNKOWN:

                    break;
            }
        }

        private void OnOpen(WebSocket websocket)
        {
            Debug.Log("[ 火山引擎智能语音合成websocket 已链接 ]");
        }
    }
}